import * as fs from 'fs';
import * as path from 'path';

/**
 * 日志级别
 */
export enum LogLevel {
  DEBUG = 'DEBUG',
  INFO = 'INFO',
  WARN = 'WARN',
  ERROR = 'ERROR',
  FATAL = 'FATAL'
}

/**
 * 日志工具类
 * 提供运行时日志记录功能，用于错误追踪和调试
 */
export class Logger {
  private static instance: Logger;
  private logFile: string;
  private maxFileSize: number = 5 * 1024 * 1024; // 5MB
  private maxBackupFiles: number = 5;
  private logLevel: LogLevel = LogLevel.INFO; // 默认日志级别为INFO

  private constructor() {
    this.ensureLogDirectory();
    this.logFile = this.getLogFilePath();
  }

  /**
   * 获取Logger实例
   */
  public static getInstance(): Logger {
    if (!Logger.instance) {
      Logger.instance = new Logger();
    }
    return Logger.instance;
  }

  /**
   * 确保日志目录存在
   */
  private ensureLogDirectory(): void {
    const logDir = this.getLogDirectory();
    if (!fs.existsSync(logDir)) {
      fs.mkdirSync(logDir, { recursive: true });
    }
  }

  /**
   * 获取日志目录路径
   */
  private getLogDirectory(): string {
    return path.join(process.cwd(), 'logs');
  }

  /**
   * 获取日志文件路径
   */
  private getLogFilePath(): string {
    const date = new Date().toISOString().split('T')[0];
    return path.join(this.getLogDirectory(), `app-${date}.log`);
  }

  /**
   * 检查并轮转日志文件
   */
  private checkAndRotateLogFile(): void {
    try {
      if (fs.existsSync(this.logFile)) {
        const stats = fs.statSync(this.logFile);
        if (stats.size > this.maxFileSize) {
          this.rotateLogFile();
        }
      }
    } catch (error) {
      console.error('日志文件轮转检查失败:', error);
    }
  }

  /**
   * 轮转日志文件
   */
  private rotateLogFile(): void {
    try {
      const logDir = this.getLogDirectory();
      const files = fs.readdirSync(logDir)
        .filter(file => file.startsWith('app-') && file.endsWith('.log'))
        .sort();

      // 删除最旧的日志文件
      while (files.length >= this.maxBackupFiles) {
        const oldestFile = files.shift();
        if (oldestFile) {
          fs.unlinkSync(path.join(logDir, oldestFile));
        }
      }

      // 创建新的日志文件
      this.logFile = this.getLogFilePath();
    } catch (error) {
      console.error('日志文件轮转失败:', error);
    }
  }

  /**
   * 设置日志级别
   */
  public setLogLevel(level: LogLevel): void {
    this.logLevel = level;
  }

  /**
   * 检查日志级别是否应该记录
   * 现在始终返回true，记录所有级别的日志
   */
  private shouldLog(level: LogLevel): boolean {
    return true;
  }

  /**
   * 写入日志
   */
  private writeLog(level: LogLevel, message: string, metadata?: any): void {
    try {
      // 检查日志级别
      if (!this.shouldLog(level)) {
        return;
      }
      
      this.checkAndRotateLogFile();

      const timestamp = new Date().toISOString();
      const logEntry = {
        timestamp,
        level,
        message,
        metadata: metadata || {},
        process: {
          pid: process.pid,
          platform: process.platform,
          version: process.version
        }
      };

      const logLine = JSON.stringify(logEntry) + '\n';
      
      fs.appendFileSync(this.logFile, logLine, { encoding: 'utf8' });

      // 同时在控制台输出
      this.consoleOutput(level, message, metadata);
    } catch (error) {
      console.error('写入日志失败:', error);
    }
  }

  /**
   * 控制台输出
   */
  private consoleOutput(level: LogLevel, message: string, metadata?: any): void {
    const colors = {
      [LogLevel.DEBUG]: '\x1b[36m', // Cyan
      [LogLevel.INFO]: '\x1b[32m',  // Green
      [LogLevel.WARN]: '\x1b[33m',  // Yellow
      [LogLevel.ERROR]: '\x1b[31m', // Red
      [LogLevel.FATAL]: '\x1b[41m'  // Red background
    };

    const reset = '\x1b[0m';
    
    // 获取UTC时间和本地时间
    const now = new Date();
    const utcTime = now.toISOString();
    const localTime = now.toLocaleString('zh-CN', { 
      timeZone: 'Asia/Shanghai',
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      hour12: false
    });
    
    const logMessage = `[${utcTime}] [${localTime}] ${colors[level]}${level}${reset}: ${message}`;
    
    if (level === LogLevel.ERROR || level === LogLevel.FATAL) {
      console.error(logMessage);
      if (metadata) {
        console.error('Metadata:', metadata);
      }
    } else if (level === LogLevel.WARN) {
      console.warn(logMessage);
    } else {
      console.log(logMessage);
    }
  }

  /**
   * 记录调试信息
   */
  public debug(message: string, metadata?: any): void {
    this.writeLog(LogLevel.DEBUG, message, metadata);
  }

  /**
   * 记录一般信息
   */
  public info(message: string, metadata?: any): void {
    this.writeLog(LogLevel.INFO, message, metadata);
  }

  /**
   * 记录警告信息
   */
  public warn(message: string, metadata?: any): void {
    this.writeLog(LogLevel.WARN, message, metadata);
  }

  /**
   * 记录错误信息
   */
  public error(message: string, error?: Error, metadata?: any): void {
    const errorInfo = {
      name: error?.name,
      message: error?.message,
      stack: error?.stack,
      ...metadata
    };
    this.writeLog(LogLevel.ERROR, message, errorInfo);
  }

  /**
   * 记录致命错误信息
   */
  public fatal(message: string, error?: Error, metadata?: any): void {
    const errorInfo = {
      name: error?.name,
      message: error?.message,
      stack: error?.stack,
      ...metadata
    };
    this.writeLog(LogLevel.FATAL, message, errorInfo);
  }

  /**
   * 记录函数调用
   */
  public logFunctionCall(functionName: string, args?: any, result?: any): void {
    this.debug(`Function called: ${functionName}`, {
      arguments: args,
      result: result
    });
  }

  /**
   * 记录性能信息
   */
  public logPerformance(functionName: string, startTime: number, endTime: number): void {
    const duration = endTime - startTime;
    this.debug(`Performance: ${functionName}`, {
      duration: `${duration}ms`,
      startTime: new Date(startTime).toISOString(),
      endTime: new Date(endTime).toISOString()
    });
  }

  /**
   * 获取最近的日志
   */
  public getRecentLogs(limit: number = 100): string[] {
    try {
      if (!fs.existsSync(this.logFile)) {
        return [];
      }

      const content = fs.readFileSync(this.logFile, 'utf8');
      const lines = content.trim().split('\n');
      return lines.slice(-limit);
    } catch (error) {
      console.error('读取日志失败:', error);
      return [];
    }
  }

  /**
   * 清空日志
   */
  public clearLogs(): void {
    try {
      if (fs.existsSync(this.logFile)) {
        fs.writeFileSync(this.logFile, '');
      }
    } catch (error) {
      console.error('清空日志失败:', error);
    }
  }
}

// 导出默认实例
export const logger = Logger.getInstance();